"""
用户CRUD操作模块

该模块提供用户数据的增删改查操作，包括用户身份验证、用户信息管理等功能。
使用SQLAlchemy ORM进行数据库操作，确保数据一致性和安全性。
"""

from sqlalchemy.orm import Session
from app.models.user import User
from app.schemas.user import LoginRequest, UserSchema
from typing import Optional, List
import hashlib
import bcrypt
import logging
import time

logger = logging.getLogger(__name__)

def get_user_by_id(db: Session, user_id: int) -> Optional[User]:
    """根据ID获取用户
    
    Args:
        db (Session): 数据库会话对象
        user_id (int): 用户ID
        
    Returns:
        Optional[User]: 用户对象，如果不存在则返回None
    """
    start_time = time.time()
    try:
        user = db.query(User).filter(User.id == user_id).first()
        elapsed = time.time() - start_time
        logger.debug(f"查询用户(ID={user_id})耗时: {elapsed:.3f}秒")
        return user
    except Exception as e:
        logger.error(f"查询用户(ID={user_id})时发生错误: {str(e)}")
        return None

def get_user_by_username(db: Session, username: str) -> Optional[User]:
    """根据用户名获取用户
    
    Args:
        db (Session): 数据库会话对象
        username (str): 用户名
        
    Returns:
        Optional[User]: 用户对象，如果不存在则返回None
    """
    start_time = time.time()
    try:
        user = db.query(User).filter(User.username == username).first()
        elapsed = time.time() - start_time
        logger.debug(f"查询用户(Username={username})耗时: {elapsed:.3f}秒")
        return user
    except Exception as e:
        logger.error(f"查询用户(Username={username})时发生错误: {str(e)}")
        return None

def get_users(db: Session, skip: int = 0, limit: int = 100) -> List[User]:
    """获取用户列表
    
    Args:
        db (Session): 数据库会话对象
        skip (int): 跳过的记录数，默认为0
        limit (int): 返回的记录数限制，默认为100
        
    Returns:
        List[User]: 用户对象列表
    """
    return db.query(User).offset(skip).limit(limit).all()

def create_user(db: Session, user: UserSchema) -> User:
    """创建用户
    
    Args:
        db (Session): 数据库会话对象
        user (UserSchema): 用户数据
        
    Returns:
        User: 创建的用户对象
    """
    db_user = User(
        username=user.username,
        name=user.name,
        email=user.email,
        role=user.role,
        avatar=user.avatar
    )
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

def authenticate_user(db: Session, username: str, password: str) -> Optional[User]:
    """验证用户身份
    
    使用bcrypt进行安全的密码验证，替代简单的SHA256哈希。
    
    Args:
        db (Session): 数据库会话对象
        username (str): 用户名
        password (str): 明文密码
        
    Returns:
        Optional[User]: 验证成功的用户对象，验证失败则返回None
    """
    start_time = time.time()
    try:
        user = get_user_by_username(db, username)
        elapsed = time.time() - start_time
        logger.debug(f"用户查询耗时: {elapsed:.3f}秒")
        
        if not user:
            logger.info(f"用户不存在: {username}")
            return None
        
        # 添加超时保护
        if elapsed > 5:  # 如果查询超过5秒，则记录警告
            logger.warning(f"用户查询超时: {username}, 耗时: {elapsed:.3f}秒")
            return None
            
        # 使用bcrypt验证密码
        start_time = time.time()
        password_match = bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8'))
        elapsed = time.time() - start_time
        logger.debug(f"密码验证耗时: {elapsed:.3f}秒")
        
        if elapsed > 5:  # 如果密码验证超过5秒，则记录警告
            logger.warning(f"密码验证超时: {username}, 耗时: {elapsed:.3f}秒")
            return None
            
        if password_match:
            logger.info(f"用户认证成功: {username}")
            return user
        else:
            logger.info(f"密码错误: {username}")
            return None
    except Exception as e:
        logger.error(f"验证用户({username})时发生错误: {str(e)}")
        return None

def update_user_last_login(db: Session, user_id: int, ip: Optional[str] = None) -> bool:
    """更新用户最后登录信息
    
    Args:
        db (Session): 数据库会话对象
        user_id (int): 用户ID
        ip (Optional[str]): 登录IP地址
        
    Returns:
        bool: 更新成功返回True，用户不存在返回False
    """
    user = get_user_by_id(db, user_id)
    if user:
        from datetime import datetime
        user.last_login_time = datetime.now()
        if ip:
            user.last_login_ip = ip
        db.commit()
        return True
    return False